<?php

namespace Gaolei\WechatPay\lib;

abstract class WechatPay extends Wechat
{

    // 发起支付 的 WECHAT 官方接口地址
    protected const MAKE_PACKAGE_URL = 'https://api.mch.weixin.qq.com/pay/unifiedorder';

    /**
     * 预生成 订单创建数据包
     * @param array $params
     * $params = [
     *    'attach' => 支付数据包
     *    'title' => 订单标题
     *    'open' => 用户openID,
     *    'order' => 你自己的商品订单号,
     *    'amount' => 付款金额，单位:元
     *    'notify' => 付款成功后的回调地址(不要有问号)
     * ];
     * @return array
     */
    abstract public function makeOrderParams(array $params): array;

    /**
     * wechat 订单数据包后处理
     * @param $packageXml
     * @return mixed
     * @author: gaolei 2021/4/24 11:54 上午
     */
    abstract public function afterTreatment($packageXml): array;

    /**
     * 统一下单
     * @param array $orderInfo 订单详情数据
     * $orderInfo = [
     *    'attach' => 支付数据包
     *    'title' => 订单标题
     *    'open' => 用户openID,
     *    'order' => 你自己的商品订单号,
     *    'amount' => 付款金额，单位:元
     *    'notify' => 付款成功后的回调地址(不要有问号)
     * ];
     * @return array
     * @throws \Exception
     */
    public function createJsBizPackage(array $orderInfo): array
    {
        $package = $this->makeOrderParams($orderInfo);
        $package['appid'] = $this->appId;                               // 公众号 APPID
        $package['attach'] = $orderInfo['attach'];                      // 支付数据包，异步回调原样返回
        $package['body'] = $orderInfo['title'];                         // 支付页显示标题
        $package['mch_id'] = $this->mchId;                              // 支付商户号
        $package['nonce_str'] = $this->createNonceStr();                // 随机字符串
        $package['notify_url'] = $orderInfo['notify'];                  // 异步回调地址，不能含有问号
        $package['out_trade_no'] = $orderInfo['order'];                 // 商家订单号
        $package['total_fee'] = $orderInfo['amount'] * 100; // 支付金额
        ksort($package, SORT_STRING);
        $package['sign'] = $this->getSign($package, $this->apiKey);     // 数据签名

        // 数据包转 xml 格式
        $xmlPackage = $this->arrayToXml($package);
        $responseXml = $this->curlPost(self::MAKE_PACKAGE_URL, $xmlPackage);
        //禁止引用外部xml实体
        libxml_disable_entity_loader(true);
        $unifiedOrder = simplexml_load_string($responseXml, 'SimpleXMLElement', LIBXML_NOCDATA);
        return $this->afterTreatment($unifiedOrder);
    }
}